package org.smart4j.framework.helper;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smart4j.framework.bean.FileParam;
import org.smart4j.framework.bean.FormParam;
import org.smart4j.framework.bean.Param;
import org.smart4j.framework.util.CollectionUtil;
import org.smart4j.framework.util.FileUtil;
import org.smart4j.framework.util.StreamUtil;
import org.smart4j.framework.util.StringUtil;

/**
 * description: 文件上传助手类
 * @version v1.0
 * @author w
 * @date 2018年10月22日下午8:45:26
 **/
public class UploadHelper {
	
	private static final Logger logger = LoggerFactory.getLogger(UploadHelper.class);
	
	/**
	 * Apache Commons FileUpload 提供的 Servlet 文件上传对象
	 */
	private static ServletFileUpload servletFileUpload;
	
	/**
	 * description: 初始化
	 * @param servletContext
	 * @return void
	 * @version v1.0
	 * @author w
	 * @date 2018年10月22日 下午8:47:49
	 */
	public static void init(ServletContext servletContext){
		File repository =(File) servletContext.getAttribute("javax.servlet.context.tempdir");
		servletFileUpload = new ServletFileUpload(new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, repository));
		int uploadLimit = ConfigHelper.getAppUploadLimit();
		if(uploadLimit != 0){
			servletFileUpload.setFileSizeMax(uploadLimit * 1024 * 1024);
		}
	}
	
	
	/**
	 * description: 判断请求是否为 Multipart 类型 --- 上传文件
	 * @param request
	 * @return boolean
	 * @version v1.0
	 * @author w
	 * @date 2018年10月22日 下午9:00:11
	 */
	public static boolean isMultipart(HttpServletRequest request){
		return ServletFileUpload.isMultipartContent(request);
	}
	
	/**
	 * description: 创建请求参数对象 Param
	 * @param request
	 * @throws IOException
	 * @return Param
	 * @version v1.0
	 * @author w
	 * @date 2018年10月22日 下午9:37:22
	 */
	public static Param createParam(HttpServletRequest request) throws IOException{
		List<FormParam> formParamList =  new ArrayList<>();
		List<FileParam> fileParamList =  new ArrayList<FileParam>();
		try {
			Map<String, List<FileItem>> fileItemListMap = servletFileUpload.parseParameterMap(request);
			if(CollectionUtil.isNotEmpty(fileItemListMap)){
				Iterator<Entry<String, List<FileItem>>> iterator = fileItemListMap.entrySet().iterator();
				while(iterator.hasNext()){
					Entry<String, List<FileItem>> next = iterator.next();
					// 表单字段名称
					String fieldName = next.getKey();
					List<FileItem> fileItemList = next.getValue();
					if(CollectionUtil.isNotEmpty(fileItemList)){
						for (FileItem fileItem : fileItemList) {
							if(fileItem.isFormField()){
								// 文件表单的字段名
								String fieldValue = fileItem.getString("UTF-8");
								formParamList.add(new FormParam(fieldName, fieldValue));
							}else{
								String fileName = FileUtil.getRealFileName(new String(fileItem.getName().getBytes(),"UTF-8"));
								if(StringUtil.isNotEmpty(fileName)){
									long fileSize = fileItem.getSize();
									String contentType = fileItem.getContentType();
									InputStream inputStream = fileItem.getInputStream();
									fileParamList.add(new FileParam(fieldName, fileName, fileSize, contentType, inputStream));
								}
							}
						}
					}
				}
			}
		} catch (FileUploadException e) {
			logger.error("create param failure ", e);
			throw new RuntimeException(e);
		}
		return new Param(formParamList,fileParamList);
	}
	
	/**
	 * description: 上传文件 
	 * @param basePath
	 * @param fileParam
	 * @return void
	 * @version v1.0
	 * @author w
	 * @date 2018年10月22日 下午9:38:25
	 */
	public static void uploadFile(String basePath,FileParam fileParam){
		try {
			if(fileParam != null){
				String filePath = basePath + fileParam.getFileName();
				FileUtil.createFile(filePath);
				InputStream inputStream = new BufferedInputStream(fileParam.getInputStream());
				OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filePath));
				StreamUtil.copyStream(inputStream , outputStream);
			}
		} catch (Exception e) {
			logger.error("upload file failure "  , e);
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * description: 批量上传文件
	 * @param basePath
	 * @param fileParamList
	 * @return void
	 * @version v1.0
	 * @author w
	 * @date 2018年10月22日 下午10:04:16
	 */
	public static void uoloadFile(String basePath , List<FileParam> fileParamList){
		try {
			if (CollectionUtil.isNotEmpty(fileParamList)) {
				for (FileParam fileParam : fileParamList) {
					uploadFile(basePath, fileParam);
				} 
			}
		} catch (Exception e) {
			logger.error("batch upload file failure " , e);
			throw new RuntimeException(e);
		}
	}
	
}
